import { Request, Response } from 'express';
import authService from '@/services/auth/auth.service';
import { AuthRequest } from '@/types';
import ApiResponse from '@/utils/api/api-response.util';
import CaptchaUtil from '@/utils/captcha.util';
import { getClientIp } from '@/utils/ip/ip.util';
import passwordService from '@/services/system/password.service';
import sysConfigService from '@/services/system/sys-config.service';
import { RepeatSubmit } from '@/decorators/repeatSubmit.decorator';
import { RateLimit } from '@/decorators/rateLimit.decorator';
import { getLogger } from '@/utils/logger';

// 创建模块专用的日志记录器
const consoleLogger = getLogger("auth-controller");
const logger = getLogger("auth-controller", {
	console: false,
});

class AuthController {
  /**
   * 用户登录
   * @param req 请求对象
   * @param res 响应对象
   */
  @RepeatSubmit({ expireSeconds: 5 })
  @RateLimit({ limit: 5, windowSeconds: 60 })
  async login(req: Request, res: Response) {
    try {
      const { username, password, code, uuid } = req.body;
      
      // 请求日志
      consoleLogger.info("用户登录请求", {
        body: { username }, // 不记录密码
        operator: 'anonymous',
      });
      
      // 参数验证
      if (!username || !password) {
        ApiResponse.error(res, '用户名和密码不能为空', 500);
        return;
      }
      
      // 获取客户端IP
      const ip = getClientIp();
      
      // 1. 校验IP是否在黑名单
      const blackIPList = await sysConfigService.getConfigValueByKey('sys.login.blackIPList');
      if (blackIPList) {
        const blackIPs = blackIPList.split(';').map((item: string) => item.trim()).filter(Boolean);
        const isBlack = blackIPs.some((pattern: string) => {
          if (pattern.includes('*')) {
            // 通配符匹配
            const regex = new RegExp('^' + pattern.replace(/\./g, '\\.').replace(/\*/g, '.*') + '$');
            return regex.test(ip);
          } else if (pattern.includes('/')) {
            // 网段匹配
            const [subnet, mask] = pattern.split('/');
            const ipToLong = (ip: string) => ip.split('.').reduce((acc, v) => acc * 256 + Number(v), 0);
            const ipLong = ipToLong(ip);
            const subnetLong = ipToLong(subnet);
            const maskBits = parseInt(mask, 10);
            const maskLong = ~((1 << (32 - maskBits)) - 1);
            return (ipLong & maskLong) === (subnetLong & maskLong);
          } else {
            // 精确匹配
            return ip === pattern;
          }
        });
        if (isBlack) {
          consoleLogger.warn("登录失败：IP在黑名单中", { ip });
          ApiResponse.error(res, '当前IP已被列入黑名单，禁止登录', 403);
          return;
        }
      }
      
      // 2. 校验验证码开关
      const captchaEnabled = await sysConfigService.getConfigValueByKey('sys.account.captchaEnabled');
      if (captchaEnabled !== 'false') {
        if (!code || !uuid) {
          consoleLogger.warn("登录失败：验证码为空", { username });
          ApiResponse.error(res, '验证码不能为空', 500);
          return;
        }
        const captchaValid = await CaptchaUtil.validate(uuid, code);
        if (!captchaValid) {
          consoleLogger.warn("登录失败：验证码错误", { username, uuid });
          ApiResponse.error(res, '验证码错误', 500);
          return;
        }
      }
      
      // 获取用户代理
      const userAgent = req.headers['user-agent'] || '';
      
      // 登录前判断账户是否被锁定
      const isLocked = await passwordService.isAccountLocked(username);
      if (isLocked) {
        consoleLogger.warn("登录失败：账户已锁定", { username });
        ApiResponse.error(res, '密码输入错误次数过多，账户已被锁定', 500);
        return;
      }
      
      // 调用登录服务
      const result = await authService.login(username, password, ip, userAgent);
      
      // 返回登录结果
      if (result.code === 200 && result.data) {
        // 结果日志
        logger.info("用户登录成功", {
          response: {
            username,
            ip,
          },
          operator: username,
        });
        
        ApiResponse.successWithoutWrapper(res, { token: result.data.token }, result.msg, result.code);
      } else {
        // 登录失败日志
        consoleLogger.warn("登录失败", {
          username,
          ip,
          code: result.code,
          msg: result.msg
        });
        
        ApiResponse.error(res, result.msg, result.code);
      }
    } catch (error) {
      // 详细的错误日志
      consoleLogger.error(`登录异常: ${error instanceof Error ? error.message : String(error)}`, {
        requestData: {
          body: { username: req.body.username }, // 不记录密码
        },
        stack: error instanceof Error ? error.stack : undefined
      });
      if (!res.headersSent) {
        ApiResponse.error(res, '登录异常，请稍后再试', 500);
      }
    }
  }
  
  /**
   * 刷新令牌
   * @param req 请求对象
   * @param res 响应对象
   */
  async refreshToken(req: Request, res: Response) {
    try {
      const { refreshToken } = req.body;
      
      // 请求日志
      consoleLogger.info("刷新令牌请求", {
        operator: req.user?.userName || 'anonymous',
      });
      
      if (!refreshToken) {
        ApiResponse.error(res, '刷新令牌不能为空', 400);
        return;
      }
      
      const result = await authService.refreshToken(refreshToken);
      
      if (result.code === 200) {
        // 结果日志
        logger.info("刷新令牌成功", {
          response: {
            code: result.code,
          },
          operator: req.user?.userName || 'anonymous',
        });
        
        ApiResponse.successWithoutWrapper(res, result.data, result.msg, result.code);
        return;
      } else {
        // 刷新失败日志
        consoleLogger.warn("刷新令牌失败", {
          code: result.code,
          msg: result.msg
        });
        
        ApiResponse.error(res, result.msg, result.code);
      }
    } catch (error) {
      // 详细的错误日志
      consoleLogger.error(`刷新令牌异常: ${error instanceof Error ? error.message : String(error)}`, {
        requestData: {
          body: req.body,
        },
        operator: req.user?.userName || 'anonymous',
        stack: error instanceof Error ? error.stack : undefined
      });
      if (!res.headersSent) {
        ApiResponse.error(res, '系统错误，刷新令牌失败', 500);
      }
    }
  }
  
  /**
   * 用户登出
   * @param req 请求对象
   * @param res 响应对象
   */
  async logout(req: AuthRequest, res: Response) {
    try {
      const userId = req.user?.userId;
      const userName = req.user?.userName || 'unknown';
      
      // 请求日志
      consoleLogger.info("用户登出请求", {
        userId,
        operator: userName,
      });
      
      if (!userId) {
        ApiResponse.error(res, '未提供有效的认证信息', 401);
        return;
      }
      
      // 获取令牌
      const authHeader = req.headers.authorization;
      let token: string | undefined;
      
      if (authHeader && authHeader.startsWith('Bearer ')) {
        token = authHeader.substring(7);
      }
      
      // 确保userId是数字类型
      const result = await authService.logout(Number(userId), userName, token);
      
      // 结果日志
      logger.info("用户登出成功", {
        response: {
          userId,
          code: result.code,
        },
        operator: userName,
      });
      
      ApiResponse.successWithoutWrapper(res, null, result.msg, result.code);
    } catch (error) {
      // 详细的错误日志
      consoleLogger.error(`登出异常: ${error instanceof Error ? error.message : String(error)}`, {
        requestData: {
          userId: req.user?.userId,
        },
        operator: req.user?.userName || 'unknown',
        stack: error instanceof Error ? error.stack : undefined
      });
      if (!res.headersSent) {
        ApiResponse.error(res, '系统错误，登出失败', 500);
      }
    }
  }
  
  /**
   * 获取当前用户信息
   * @param req 请求对象
   * @param res 响应对象
   */
  async getUserInfo(req: AuthRequest, res: Response) {
    try {
      const userId = req.user?.userId;
      const userName = req.user?.userName || 'unknown';
      
      // 请求日志
      consoleLogger.info("获取当前用户信息请求", {
        userId,
        operator: userName,
      });
      
      if (!req.user || !userId) {
        ApiResponse.error(res, '未提供有效的认证信息', 401);
        return;
      }
      
      // 获取用户详细信息，包括部门和角色
      const userInfo = await authService.getUserDetailInfo(Number(userId));
      
      if (!userInfo) {
        ApiResponse.error(res, '获取用户信息失败', 500);
        return;
      }
      
      // 判断是否为管理员
      const isAdmin = await authService.isAdmin(Number(userId));
      
      // 获取角色标识
      const roleKeys = userInfo.roles?.map((role: any) => role.roleKey) || [];
      
      // 构建返回数据
      const responseData = {
        permissions: isAdmin ? ['*:*:*'] : req.user.permissions,
        roles: roleKeys,
        user: {
          ...userInfo,
          admin: isAdmin
        }
      };
      
      // 结果日志
      logger.info("获取当前用户信息成功", {
        response: {
          userId,
          isAdmin,
          roleCount: roleKeys.length,
        },
        operator: userName,
      });
      
      ApiResponse.successWithoutWrapper(res, responseData, '操作成功', 200);
    } catch (error) {
      // 详细的错误日志
      consoleLogger.error(`获取用户信息异常: ${error instanceof Error ? error.message : String(error)}`, {
        requestData: {
          userId: req.user?.userId,
        },
        operator: req.user?.userName || 'unknown',
        stack: error instanceof Error ? error.stack : undefined
      });
      if (!res.headersSent) {
        ApiResponse.error(res, '系统错误，获取用户信息失败', 500);
      }
    }
  }
}

export default new AuthController(); 